openapi: 3.0.3
info:
  title: Spakinect EMR Integration API
  description: >
    API for External Electronic Medical Record (EMR) systems to integrate with
    Spakinect telemedicine platform. Provides endpoints for managing
    appointments, retrieving treatments, and checking visit statuses.
  version: 1.0.0
  contact:
    name: Spakinect Support
    email: support@spakinect.com
servers:
  - url: https://us-central1-spakinect-app.cloudfunctions.net/emr
    description: Production Server
  - url: https://us-central1-spakinect-staging.cloudfunctions.net/emr
    description: Staging Server
security:
  - ApiKeyAuth: []
tags:
  - name: Appointments
    description: Operations for creating and managing Good Faith Exam appointments
  - name: GFEs
    description: Operations for retrieving Good Faith Exam visits by location
  - name: Treatments
    description: Operations for retrieving available medical treatments
  - name: InPerson
    description: Operations for creating and managing in-person intake visits
  - name: Subscriptions
    description: Operations for managing location subscriptions
paths:
  /appointments:
    post:
      summary: Creates a new At-Home Visit
      description: >
        Creates a new At-Home Visit (Good Faith Exam (GFE)) in the Spakinect
        system. The patient will be emailed and texted a link to complete their
        GFE prior to their appointment at the medspa. Optionally, EMR systems
        can submit intake answers when creating the appointment; these are
        pre-filled for the patient when they start the visit.
      operationId: createAppointment
      tags:
        - Appointments
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAppointmentRequest'
            examples:
              standard_appointment:
                summary: Standard appointment creation
                value:
                  patient_details:
                    first_name: John
                    last_name: Doe
                    email: john.doe@example.com
                    phone: '+1234567890'
                  location_id: loc_12345
                  appointment_time: 1640995200
                  requested_treatments:
                    - Botox Injection
                    - Dermal Filler
              with_intake_answers:
                summary: Appointment with EMR-submitted intake answers
                value:
                  patient_details:
                    first_name: Jane
                    last_name: Smith
                    email: jane.smith@example.com
                    phone: '+1987654321'
                  location_id: loc_12345
                  appointment_time: 1640995200
                  requested_treatments:
                    - Botox Injection
                  intake_answers:
                    - question: pregnant-breastfeeding-ivf
                      answer: 'No'
                    - question: allergies
                      answer:
                        selected: 'yes'
                        items:
                          - Penicillin
                    - question: medical-conditions
                      answer:
                        selected: 'no'
                        items: []
                    - question: medications
                      answer:
                        selected: 'yes'
                        items:
                          - Aspirin
                          - Vitamin D
      responses:
        '201':
          description: Appointment created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateAppointmentResponse'
              examples:
                success:
                  summary: Successful appointment creation
                  value:
                    success: true
                    gfe_id: gfe_abc123xyz789
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /treatments:
    get:
      summary: Get Available Treatments
      description: >
        Retrieves treatments. Returns all available treatments by default, or
        favorite

        treatments when type=favorites and location_id are provided.


        **URLs:**

        - All treatments: `GET /treatments`

        - Favorite treatments: `GET
        /treatments?type=favorites&location_id=<location_id>`
      operationId: getTreatments
      tags:
        - Treatments
      parameters:
        - name: type
          in: query
          required: false
          description: >
            When set to 'favorites', returns the client's favorite treatments
            for the given location. Requires location_id.
          schema:
            type: string
            enum:
              - favorites
        - name: location_id
          in: query
          required: false
          description: >
            Required when type=favorites. The unique identifier of the location.
            Used to resolve the client and fetch their favorite treatments.
          schema:
            type: string
            example: loc_12345
      responses:
        '200':
          description: List of available treatments
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TreatmentsResponse'
              examples:
                treatments_list:
                  summary: All available treatments (GET /treatments)
                  value:
                    data:
                      - id: treatment_001
                        name: Botox Injection
                      - id: treatment_002
                        name: Dermal Filler
                      - id: treatment_003
                        name: Chemical Peel
                favorites_list:
                  summary: >-
                    Favorite treatments (GET
                    /treatments?type=favorites&location_id=...)
                  value:
                    data:
                      - id: treatment_001
                        name: Botox Injection
                      - id: treatment_002
                        name: Dermal Filler
                    source: favorites
        '400':
          description: Bad request - Missing location_id when type=favorites
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                missing_location_id_favorites:
                  summary: location_id required for favorites
                  value:
                    success: false
                    error: location_id is required when requesting favorites
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: >
            Location not found (when type=favorites). For all treatments, empty
            list returns 200 with data: [].
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                location_not_found:
                  summary: Location not found when requesting favorites
                  value:
                    success: false
                    error: Location not found
        '500':
          $ref: '#/components/responses/InternalServerError'
  /gfes/{location_id}:
    get:
      summary: Get All GFEs by Location
      description: >
        Retrieves all Good Faith Exam (GFE) visits for a specific location. Only
        returns visits that the authenticated EMR has access to based on
        location permissions. When visit status is "Completed", each visit
        includes decision outcomes mapped to treatment names:
        approved_treatments, conditionally_approved_treatments, and
        deferred_treatments.
      operationId: getAllGFEsByLocation
      tags:
        - GFEs
      parameters:
        - name: location_id
          in: path
          required: true
          description: The unique identifier of the location
          schema:
            type: string
            example: loc_12345
      responses:
        '200':
          description: List of GFEs retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GFEsByLocationResponse'
              examples:
                gfes_list:
                  summary: List of GFEs for location
                  value:
                    success: true
                    location_id: loc_12345
                    count: 2
                    gfes:
                      - gfe_id: gfe_abc123xyz789
                        status: Completed
                        requested_treatments:
                          - Botox Injection
                          - Dermal Filler
                        approved_treatments:
                          - Botox Injection
                        conditionally_approved_treatments:
                          - Dermal Filler
                        deferred_treatments: []
                        pdf_link: https://example-cdn.com/gfe/gfe_abc123xyz789.pdf
                        evaluation_completed: '2024-05-02T07:00:00-07:00'
                        patient_details:
                          name: Jane Smith
                          first_name: Jane
                          last_name: Smith
                          dob: 05-15-1985
                          email: jane.smith@example.com
                      - gfe_id: gfe_def456uvw012
                        status: Processing
                        requested_treatments:
                          - Chemical Peel
                        patient_details:
                          name: John Doe
                          first_name: John
                          last_name: Doe
                          dob: 10-27-1990
                          email: john.doe@example.com
                empty_list:
                  summary: No GFEs found for location
                  value:
                    success: true
                    location_id: loc_12345
                    count: 0
                    gfes: []
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /visits/{gfe_id}:
    get:
      summary: Get Visit Status
      description: >
        Retrieves the current status and details of a Good Faith Exam (GFE)
        visit by ID. Only returns visits that the authenticated EMR has access
        to based on location permissions. When the visit status is "Completed",
        the response includes decision outcomes mapped to treatment names:
        approved_treatments, conditionally_approved_treatments, and
        deferred_treatments.
      operationId: getVisitStatus
      tags:
        - Appointments
        - InPerson
      parameters:
        - name: gfe_id
          in: path
          required: true
          description: The unique identifier of the GFE visit
          schema:
            type: string
            example: gfe_abc123xyz789
      responses:
        '200':
          description: Visit status retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VisitStatusResponse'
              examples:
                completed_status:
                  summary: Completed visit
                  value:
                    success: true
                    data:
                      gfe_id: gfe_abc123xyz789
                      status: Completed
                      requested_treatments:
                        - Botox Injection
                      approved_treatments:
                        - Botox Injection
                      conditionally_approved_treatments:
                        - Dermal Filler
                      deferred_treatments:
                        - Chemical Peel
                      pdf_link: https://example-cdn.com/gfe/gfe_abc123xyz789.pdf
                      evaluation_completed: '2024-05-02T07:00:00-07:00'
                      patient_details:
                        name: Jane Smith
                        first_name: Jane
                        last_name: Smith
                        dob: 05-15-1985
                        email: jane.smith@example.com
                processing_status:
                  summary: Visit in processing status
                  value:
                    success: true
                    data:
                      gfe_id: gfe_abc123xyz789
                      status: Processing
                      requested_treatments:
                        - Botox Injection
                        - Dermal Filler
                      patient_details:
                        name: John Doe
                        first_name: John
                        last_name: Doe
                        dob: 10-27-1990
                        email: john.doe@example.com
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /appointments/{gfe_id}/cancel:
    patch:
      summary: Cancels an At-Home Visit
      description: >
        Cancels an At-Home Visit Good Faith Exam by ID. Only visits with status
        "Processing", "Scheduled", or "Not Completed" can be cancelled. The
        visit status will be updated to "Cancelled by client". Only appointments
        that the authenticated EMR has access to based on location permissions
        can be cancelled.
      operationId: cancelAppointment
      tags:
        - Appointments
      parameters:
        - name: gfe_id
          in: path
          required: true
          description: The unique identifier of the GFE appointment to cancel
          schema:
            type: string
            example: gfe_abc123xyz789
      responses:
        '200':
          description: Appointment cancelled successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CancelAppointmentResponse'
              examples:
                success:
                  summary: Successful cancellation
                  value:
                    gfe_id: gfe_abc123xyz789
                    status: Cancelled by client
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /in-person:
    post:
      summary: Create a new in-person visit
      description: >
        Creates a new in-person visit for a patient. If a matching patient is
        found by name and date of birth, their record is used; otherwise, a new
        patient record is created. Optionally, EMR systems can submit intake
        answers when creating the visit; these are pre-filled for the patient
        when they open the intake form.
      operationId: createInPersonVisit
      tags:
        - InPerson
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InPersonVisitCreationRequest'
            examples:
              standard_visit:
                summary: Standard in-person visit creation
                value:
                  patient_details:
                    first_name: John
                    last_name: Doe
                    dob: 10/27/1990
                  location_id: loc_12345
                  requested_treatments:
                    - Botox Injection
                    - Dermal Filler
              with_intake_answers:
                summary: In-person visit with EMR-submitted intake answers
                value:
                  patient_details:
                    first_name: Jane
                    last_name: Smith
                    dob: 05/14/1985
                  location_id: loc_12345
                  requested_treatments:
                    - Botox Injection
                  intake_answers:
                    - question: pregnant-breastfeeding-ivf
                      answer: 'No'
                    - question: allergies
                      answer:
                        selected: 'yes'
                        items:
                          - Penicillin
                    - question: medical-conditions
                      answer:
                        selected: 'no'
                        items: []
                    - question: medications
                      answer:
                        selected: 'yes'
                        items:
                          - Aspirin
                          - Vitamin D
      responses:
        '201':
          description: In-person visit created successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InPersonVisitCreationResponse'
              examples:
                success:
                  summary: Successful in-person visit creation
                  value:
                    success: true
                    visit_id: gfe_abc123xyz789
                    visit_link: https://client.spakinect.com/visit/gfe_abc123xyz789
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /webhooks:
    post:
      summary: Register Webhook URL
      description: >
        Registers or updates the webhook URL for the authenticated EMR.


        **Note:** To receive webhook events, a location must be subscribed to
        the EMR

        using the Location subscription endpoint (`POST /subscriptions`).


        When a GFE is completed, Spakinect will send a POST request to the
        registered

        URL with the payload described in `VisitCompletedWebhook`.


        - Event: `visit.completed`

        - Headers: `Content-Type: application/json`, `User-Agent:
        Spakinect-Webhook/1.0`,
          and if configured `X-Webhook-Secret: <secret>`.
        - Schema: `#/components/schemas/VisitCompletedWebhook`
      operationId: registerWebhook
      tags:
        - Webhooks
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookRegistrationRequest'
            examples:
              webhook_registration:
                summary: Register webhook URL
                value:
                  url: https://example.com/webhooks/emr-callback
      responses:
        '200':
          description: Webhook URL registered successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookRegistrationResponse'
              examples:
                success:
                  summary: Successful webhook registration
                  value:
                    success: true
                    message: Webhook URL updated successfully
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /subscriptions:
    post:
      summary: Subscribe to Location
      description: >
        Subscribes the authenticated EMR to a location. This adds the location
        to the EMR's subscribed locations list. This endpoint is required to
        receive webhook events for the location.
      operationId: subscribeToLocation
      tags:
        - Subscriptions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionRequest'
            examples:
              location_subscription:
                summary: Subscribe to location
                value:
                  location_id: loc_12345
      responses:
        '200':
          description: Successfully subscribed to location or already subscribed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionResponse'
              examples:
                success:
                  summary: Successful subscription
                  value:
                    success: true
                    message: Successfully subscribed to location
                already_subscribed:
                  summary: Already subscribed
                  value:
                    success: true
                    message: Already subscribed to this location
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >
        API key provided by Spakinect for EMR integration. This key must be
        associated with at least one location that the EMR system has access to.
  schemas:
    CreateAppointmentRequest:
      type: object
      required:
        - patient_details
        - location_id
        - appointment_time
        - requested_treatments
      properties:
        patient_details:
          $ref: '#/components/schemas/PatientDetails'
        location_id:
          type: string
          description: The ID of the location where the appointment will take place
          example: loc_12345
        appointment_time:
          type: integer
          description: >
            Unix timestamp of the appointment date and time with the medspa.
            This is different from the appointment time with Spakinect
            (provider). To schedule an appointment with a Spakinect provider,
            the patient can use the Schedule link in the email sent from
            Spakinect.
          example: 1640995200
          minimum: 1
        requested_treatments:
          type: array
          description: List of treatment names requested for this appointment
          items:
            type: string
          minItems: 1
          example:
            - Botox Injection
            - Dermal Filler
        intake_answers:
          x-optional: true
          type: array
          description: >
            Submit intake question answers while creating the appointment for
            at-home visit patients so they can review and modify them if needed.


            Supported question codes:

            - pregnant-breastfeeding-ivf (pregnancy/breastfeeding/IVF status)

            - medications

            - allergies

            - medical-conditions
          items:
            type: object
            required:
              - question
              - answer
            properties:
              question:
                type: string
                description: >
                  The question_code. Supported: pregnant-breastfeeding-ivf,
                  allergies, medical-conditions, medications.
              answer:
                oneOf:
                  - type: string
                    description: >-
                      For single choice (pregnant-breastfeeding-ivf). Must be
                      "Yes", "No", or "N/A".
                    enum:
                      - 'Yes'
                      - 'No'
                      - N/A
                  - type: object
                    description: >-
                      For yes_no_list (allergies, medical-conditions,
                      medications). When selected is "no", items must be [].
                    required:
                      - selected
                      - items
                    properties:
                      selected:
                        type: string
                        enum:
                          - 'yes'
                          - 'no'
                      items:
                        type: array
                        description: List of items (must be empty when selected is "no")
                        items:
                          type: string
      additionalProperties: false
    CreateAppointmentResponse:
      type: object
      required:
        - success
        - gfe_id
      properties:
        success:
          type: boolean
          description: Indicates if the appointment was created successfully
          example: true
        gfe_id:
          type: string
          description: Unique identifier for the created GFE appointment
          example: gfe_abc123xyz789
      additionalProperties: false
    CancelAppointmentResponse:
      type: object
      required:
        - gfe_id
        - status
      properties:
        gfe_id:
          type: string
          description: Unique identifier for the cancelled GFE appointment
          example: gfe_abc123xyz789
        status:
          type: string
          description: The updated status of the appointment after cancellation
          example: Cancelled by client
      additionalProperties: false
    PatientDetails:
      type: object
      required:
        - first_name
        - last_name
        - email
        - phone
      properties:
        first_name:
          type: string
          description: Patient's first name
          example: John
          minLength: 1
          maxLength: 100
        last_name:
          type: string
          description: Patient's last name
          example: Doe
          minLength: 1
          maxLength: 100
        email:
          type: string
          format: email
          description: Patient's email address
          example: john.doe@example.com
        phone:
          type: string
          description: Patient's phone number
          example: '+1234567890'
          pattern: ^\+?[1-9]\d{1,14}$
      additionalProperties: false
    VisitPatientDetails:
      type: object
      required:
        - name
        - first_name
        - last_name
        - email
      properties:
        name:
          type: string
          description: Patient's full name
          example: John Doe
        first_name:
          type: string
          description: Patient's first name
          example: John
        last_name:
          type: string
          description: Patient's last name
          example: Doe
        email:
          type: string
          format: email
          description: Patient's email address
          example: john.doe@example.com
        dob:
          type: string
          description: Patient's date of birth in MM-DD-YYYY format
          example: 10-27-1990
          pattern: ^\d{2}-\d{2}-\d{4}$
      additionalProperties: false
    Treatment:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: string
          description: Unique identifier for the treatment
          example: treatment_001
        name:
          type: string
          description: Display name of the treatment
          example: Botox Injection
      additionalProperties: false
    TreatmentsResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: array
          description: List of available treatments
          items:
            $ref: '#/components/schemas/Treatment'
        source:
          type: string
          description: >
            Present when type=favorites. Indicates the treatments are from the
            client's favorite configuration.
          enum:
            - favorites
          example: favorites
      additionalProperties: false
    VisitData:
      type: object
      required:
        - gfe_id
        - status
        - requested_treatments
        - patient_details
      properties:
        gfe_id:
          type: string
          description: Unique identifier for the GFE visit
          example: gfe_abc123xyz789
        status:
          type: string
          description: Current status of the visit
          enum:
            - Processing
            - Pending Review
            - Approved
            - Completed
            - Cancelled
            - Rejected
          example: Processing
        requested_treatments:
          type: array
          description: List of treatments requested for this visit
          items:
            type: string
          example:
            - Botox Injection
            - Dermal Filler
        patient_details:
          $ref: '#/components/schemas/VisitPatientDetails'
        approved_treatments:
          type: array
          description: Present only when status is Completed. Names of treatments approved.
          items:
            type: string
          example:
            - Botox Injection
        conditionally_approved_treatments:
          type: array
          description: >
            Present only when status is Completed. Names of treatments approved
            with conditions.
          items:
            type: string
          example:
            - Dermal Filler
        deferred_treatments:
          type: array
          description: Present only when status is Completed. Names of treatments deferred.
          items:
            type: string
          example:
            - Chemical Peel
        pdf_link:
          type: string
          format: uri
          description: >
            URL to the generated GFE PDF, if available. Present only when a PDF
            has been generated for the visit.
          example: https://example-cdn.com/gfe/gfe_abc123xyz789.pdf
        evaluation_completed:
          type: string
          format: date-time
          description: >
            ISO 8601 datetime when the provider completed the evaluation, in
            Pacific time (PST/PDT). Present only when status is Completed.
            Example: 2024-05-02T07:00:00-07:00
          example: '2024-05-02T07:00:00-07:00'
      additionalProperties: false
    VisitStatusResponse:
      type: object
      required:
        - success
        - data
      properties:
        success:
          type: boolean
          description: Indicates if the request was processed successfully
          example: true
        data:
          $ref: '#/components/schemas/VisitData'
      additionalProperties: false
    GFEsByLocationResponse:
      type: object
      required:
        - success
        - location_id
        - count
        - gfes
      properties:
        success:
          type: boolean
          description: Indicates if the request was processed successfully
          example: true
        location_id:
          type: string
          description: The unique identifier of the location
          example: loc_12345
        count:
          type: integer
          description: The number of GFEs returned for this location
          example: 2
          minimum: 0
        gfes:
          type: array
          description: List of GFE visits for the location
          items:
            $ref: '#/components/schemas/VisitData'
      additionalProperties: false
    InPersonVisitCreationRequest:
      type: object
      title: In-person Visit Creation Request
      required:
        - patient_details
        - location_id
        - requested_treatments
      properties:
        patient_details:
          type: object
          required:
            - first_name
            - last_name
            - dob
          properties:
            first_name:
              type: string
              description: The patient's first name.
            last_name:
              type: string
              description: The patient's last name.
            dob:
              type: string
              description: The patient's date of birth in MM/DD/YYYY format.
              example: 10/27/1990
        location_id:
          type: string
          description: The ID of the location where the visit will take place.
          example: loc_12345
        requested_treatments:
          type: array
          description: A non-empty list of treatment names requested for the visit.
          minItems: 1
          items:
            type: string
          example:
            - Botox Injection
            - Dermal Filler
        intake_answers:
          x-optional: true
          type: array
          description: |
            Submit intake question answers while creating the visit so the
            patient sees them pre-filled when they open the intake form.

            Supported question codes:
            - pregnant-breastfeeding-ivf (pregnancy/breastfeeding/IVF status)
            - medications
            - allergies
            - medical-conditions
          items:
            type: object
            required:
              - question
              - answer
            properties:
              question:
                type: string
                description: >
                  The question_code of the intake question. Supported values:
                  pregnant-breastfeeding-ivf, allergies, medical-conditions,
                  medications.
              answer:
                oneOf:
                  - type: string
                    description: >-
                      For single choice questions (e.g.
                      pregnant-breastfeeding-ivf). Must be "Yes", "No", or
                      "N/A".
                    enum:
                      - 'Yes'
                      - 'No'
                      - N/A
                  - type: object
                    description: >-
                      For yes_no_list questions (allergies, medical-conditions,
                      medications). When selected is "no", items must be [].
                    required:
                      - selected
                      - items
                    properties:
                      selected:
                        type: string
                        enum:
                          - 'yes'
                          - 'no'
                      items:
                        type: array
                        description: List of items (must be empty when selected is "no").
                        items:
                          type: string
      additionalProperties: false
    InPersonVisitCreationResponse:
      type: object
      title: In-person Visit Creation Response
      required:
        - success
        - visit_id
        - visit_link
      properties:
        success:
          type: boolean
          description: Indicates if the operation was successful.
        visit_id:
          type: string
          description: The unique ID of the newly created visit.
          example: gfe_abc123xyz789
        visit_link:
          type: string
          format: uri
          description: A direct URL to the visit intake form.
          example: https://client.spakinect.com/visit/gfe_abc123xyz789
      additionalProperties: false
    ErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          description: Always false for error responses
          example: false
        error:
          type: string
          description: Error message describing what went wrong
          example: Missing required patient details
        message:
          type: string
          description: Additional context about the error (optional)
          example: The first_name field is required but was not provided
      additionalProperties: false
    WebhookRegistrationRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          format: uri
          description: The webhook URL where events will be posted
          example: https://example.com/webhooks/emr-callback
      additionalProperties: false
    WebhookRegistrationResponse:
      type: object
      required:
        - success
        - message
      properties:
        success:
          type: boolean
          description: Indicates if the webhook URL was registered successfully
          example: true
        message:
          type: string
          description: Success message
          example: Webhook URL updated successfully
      additionalProperties: false
    VisitCompletedWebhook:
      type: object
      title: Visit Completed Webhook
      description: |
        Payload delivered to the EMR webhook URL when a GFE visit is completed.
      required:
        - event
        - timestamp
        - success
        - data
      properties:
        event:
          type: string
          description: The webhook event type.
          enum:
            - visit.completed
          example: visit.completed
        timestamp:
          type: integer
          description: Unix timestamp (milliseconds) when the webhook was generated.
          example: 1714675200000
        success:
          type: boolean
          description: Indicates if the visit data retrieval was successful.
          example: true
        data:
          $ref: '#/components/schemas/VisitCompletedWebhookData'
      example:
        event: visit.completed
        timestamp: 1714675200000
        success: true
        data:
          location_id: loc_12345
          gfe_id: gfe_abc123xyz789
          status: Completed
          pdf_link: https://example-cdn.com/gfe/gfe_abc123xyz789.pdf
          requested_treatments:
            - Botox Injection
            - Dermal Filler
          approved_treatments:
            - Botox Injection
          conditionally_approved_treatments:
            - Dermal Filler
          deferred_treatments: []
          evaluation_completed: '2024-05-02T07:00:00-07:00'
          patient_details:
            name: Jane Smith
            first_name: Jane
            last_name: Smith
            dob: 05-15-1985
            email: jane.smith@example.com
    VisitCompletedWebhookData:
      type: object
      title: Visit Completed Webhook Data
      required:
        - location_id
        - gfe_id
        - status
        - requested_treatments
        - patient_details
      properties:
        location_id:
          type: string
          description: The ID of the location where the visit took place.
          example: loc_12345
        gfe_id:
          type: string
          description: Unique identifier for the GFE visit.
          example: gfe_abc123xyz789
        status:
          type: string
          description: Final status of the visit.
          enum:
            - Completed
          example: Completed
        pdf_link:
          type: string
          format: uri
          description: URL to the generated GFE PDF, if available.
          example: https://example-cdn.com/gfe/gfe_abc123xyz789.pdf
        requested_treatments:
          type: array
          description: List of treatments originally requested for this visit.
          items:
            type: string
          example:
            - Botox Injection
            - Dermal Filler
        patient_details:
          $ref: '#/components/schemas/VisitPatientDetails'
        approved_treatments:
          type: array
          description: >
            Names of treatments approved by the provider. Present when status is
            Completed.
          items:
            type: string
          example:
            - Botox Injection
        conditionally_approved_treatments:
          type: array
          description: >
            Names of treatments that are conditionally approved. Present when
            status is Completed.
          items:
            type: string
          example:
            - Dermal Filler
        deferred_treatments:
          type: array
          description: >
            Names of treatments deferred to a later time. Present when status is
            Completed.
          items:
            type: string
          example:
            - Chemical Peel
        evaluation_completed:
          type: string
          format: date-time
          description: >
            ISO 8601 datetime when the provider completed the evaluation, in
            Pacific time (PST/PDT).
          example: '2024-05-02T07:00:00-07:00'
      additionalProperties: false
    SubscriptionRequest:
      type: object
      required:
        - location_id
      properties:
        location_id:
          type: string
          description: The ID of the location to subscribe to
          example: loc_12345
      additionalProperties: false
    SubscriptionResponse:
      type: object
      required:
        - success
        - message
      properties:
        success:
          type: boolean
          description: Indicates if the subscription was successful
          example: true
        message:
          type: string
          description: Success message indicating subscription status
          example: Successfully subscribed to location
      additionalProperties: false
  responses:
    BadRequest:
      description: Bad request - Invalid input parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missing_required_fields:
              summary: Missing required fields
              value:
                success: false
                error: Missing required patient details
            invalid_gfe_id:
              summary: Invalid GFE ID format
              value:
                success: false
                error: GFE ID is required
            missing_webhook_url:
              summary: Missing webhook URL
              value:
                success: false
                error: Bad Request
                message: URL field is required in request body
            invalid_webhook_url:
              summary: Invalid webhook URL format
              value:
                success: false
                error: Bad Request
                message: Invalid URL format
            missing_location_id:
              summary: Missing location ID
              value:
                success: false
                error: Bad Request
                message: location_id field is required in request body
            empty_location_id:
              summary: Empty location ID
              value:
                success: false
                error: Bad Request
                message: location_id cannot be empty
            missing_location_id_path:
              summary: Missing location_id path parameter
              value:
                success: false
                error: location_id path parameter is required
    Unauthorized:
      description: Unauthorized - Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missing_api_key:
              summary: Missing API key
              value:
                success: false
                error: 'Unauthorized: API key is missing.'
            invalid_api_key:
              summary: Invalid API key
              value:
                success: false
                error: 'Forbidden: Invalid API key.'
    Forbidden:
      description: Forbidden - EMR not authorized for requested resource
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            location_access_denied:
              summary: No access to location
              value:
                success: false
                error: EMR is not authorized for this location
            gfe_access_denied:
              summary: No access to GFE
              value:
                success: false
                error: EMR is not authorized to access this GFE
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            gfe_not_found:
              summary: GFE not found
              value:
                success: false
                error: GFE not found
            location_not_found:
              summary: Location not found
              value:
                success: false
                error: Not Found
                message: Location not found
            emr_not_found:
              summary: EMR document not found
              value:
                success: false
                error: Not Found
                message: EMR document not found
            endpoint_not_found:
              summary: Endpoint not found
              value:
                success: false
                error: Not found
                message: EMR endpoint /invalid-path not found
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            server_error:
              summary: Generic server error
              value:
                success: false
                error: Internal server error
            auth_error:
              summary: Authentication service error
              value:
                success: false
                error: Internal Server Error during authentication.
